package com.example.graphictest;

import java.util.ArrayList;
import java.util.Formatter;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.View;

public class MyView extends View {

	Paint paint = new Paint();

	// private Circle c1;
	// private Circle c2;

	private float touchX;
	private float touchY;
	private float touchXPre;
	private float touchYPre;

	private int moveSpeed;
	private float speedX;
	private float speedY;

	private boolean isTouchReleased;

	private int canvasWidth;
	private int canvasHeight;
	private boolean canvasInited;
	
    float deltaTime = 0;
    float startTime = 0;
	


	ArrayList<Circle> circleList;

	StringBuilder sb = new StringBuilder();
	Formatter formatter = new Formatter(sb);

	public MyView(Context context) {
		super(context);
		// TODO Auto-generated constructor stub

		// c1 = new Circle(200, 200, 50, Color.RED);
		// c2 = new Circle(200, 500, 100, Color.GREEN);
		circleList = new ArrayList<Circle>();
		circleList.add(new Circle(200, 200, 50, Color.RED));
//		circleList.add(new Circle(200, 300, 100, Color.GREEN));
//		circleList.add(new Circle(300, 500, 60, Color.BLUE));
//		circleList.add(new Circle(400, 600, 20, Color.MAGENTA));
//		circleList.add(new Circle(200, 100, 30, Color.BLACK));
//		circleList.add(new Circle(200, 250, 70, Color.YELLOW));
//		circleList.add(new Circle(300, 230, 60, Color.CYAN));
//		circleList.add(new Circle(310, 300, 40, Color.LTGRAY));
		touchX = 0;
		touchY = 0;
		touchXPre = 0;
		touchYPre = 0;
		moveSpeed = 2;

		speedX = 0;
		speedY = 0;

		isTouchReleased = false;

		canvasWidth = 0;
		canvasHeight = 0;
		canvasInited = false;
		

		// new Thread(new Runnable() {
		// public void run() {
		// while(true){
		// try {
		// Thread.sleep(10);
		// //y++;
		// postInvalidate();
		// } catch (InterruptedException e) {
		// e.printStackTrace();
		// }
		// }
		// }
		// }).start();
	}

	public void onDraw(Canvas canvas) {

		canvasWidth = canvas.getWidth();
		canvasHeight = canvas.getHeight();
		canvasInited = true;

		for (int i = 0; i < circleList.size(); i++) {
			paint.setColor(circleList.get(i).getColor());
			canvas.drawCircle(circleList.get(i).getPosX(), circleList.get(i)
					.getPosY(), circleList.get(i).getRadius(), paint);
		}

		paint.setColor(Color.BLACK);
		paint.setTextSize(30);
		canvas.drawText("touch position:" + touchX + "," + touchY, 30, 30,
				paint);
		canvas.drawText("touch speed:" + (touchX - touchXPre) + ","
				+ (touchY - touchYPre), 30, 60, paint);
		canvas.drawText("canvas size:" + canvasWidth + "," + canvasHeight, 30,
				90, paint);

		paint.setTextSize(15);
		for (int i = 0; i < circleList.size(); i++) {

			// formatter.format("Ball @(%3.0f,%3.0f) Speed=(%2.0f,%2.0f)",
			// circleList.get(i).getPosX(), circleList.get(i).getPosY(),
			// circleList.get(i).getSpeedX(), circleList.get(i).getSpeedY());
			// canvas.drawText(sb.toString(), 30, 90+30*(i+1), paint);

//			float energyX = circleList.get(i).getMass()*circleList.get(i).getSpeedX()*circleList.get(i).getSpeedX();
//			float energyY = circleList.get(i).getMass()*circleList.get(i).getSpeedY()*circleList.get(i).getSpeedY();
			float energySum = 0.0f; //energyX + energyY;
			canvas.drawText(i + " pos:" + (int) circleList.get(i).getPosX()
					+ "," + (int) circleList.get(i).getPosY() + " speed:"
					+ (int)circleList.get(i).getSpeedX() + ","
					+ (int)circleList.get(i).getSpeedY() + ", energy:" + (int)energySum, 30, 90 + 30 * (i + 1),
					paint);

		}
	}

	public Paint getPaint() {
		return paint;
	}

	public void setPaint(Paint paint) {
		this.paint = paint;
	}

	public void touchTriggerDown(float x, float y) {
		// TODO Auto-generated method stub

		touchXPre = touchX;
		touchYPre = touchY;
		touchX = x;
		touchY = y;

		// c1.checkInside(x, y);
		// c2.checkInside(x, y);
		for (int i = 0; i < circleList.size(); i++) {
			circleList.get(i).checkInside(x, y);
		}

		isTouchReleased = false;
	}

	public void touchTriggerMove(float x, float y) {
		// TODO Auto-generated method stub
		touchXPre = touchX;
		touchYPre = touchY;
		touchX = x;
		touchY = y;
		startTime = System.nanoTime();
		
		for (int i = 0; i < circleList.size(); i++) {
			circleList.get(i).updatePos(x, y, moveSpeed);
		}
		// c1.updatePos(x, y, moveSpeed);
		// c2.updatePos(x, y, moveSpeed);
	}

	public void touchTriggerUp(float x, float y) {
		// TODO Auto-generated method stub
		// touchXPre = touchX;
		// touchYPre = touchY;
		// touchX = (int) x;
		// touchY = (int) y;

		// c1.updatePos(x, y, moveSpeed);
		// c2.updatePos(x, y, moveSpeed);

		float deltaTime = (System.nanoTime()-startTime) / 1000000000.0f;
		speedX = (touchX - touchXPre)/deltaTime;
		speedY = (touchY - touchYPre)/deltaTime;

		for (int i = 0; i < circleList.size(); i++) {
			circleList.get(i).setSpeed(speedX, speedY);
		}
		// c1.setSpeed(speedX, speedY);
		// c2.setSpeed(speedX, speedY);

		isTouchReleased = true;
	}

	public void update(float deltaTime) {
		// TODO Auto-generated method stub
		// if(isTouchReleased)
		

        
		{
			// c1.updatePos(canvasWidth, canvasHeight);
			// c2.updatePos(canvasWidth, canvasHeight);
			if (canvasInited) {
				for (int i = 0; i < circleList.size(); i++) {
					circleList.get(i).updatePosDeltaTime(deltaTime, canvasWidth, canvasHeight);
				}
			}
			// c1.updatePos(540, 850);
			// c2.updatePos(540, 850);

			// collision and bouncing
			// checkIntersect(c1, c2);
			for (int i = 0; i < circleList.size() - 1; i++) {
				for (int j = 1; j < circleList.size(); j++) {
					checkIntersect(circleList.get(i), circleList.get(j));
				}
			}

		}
	}

	public static void checkIntersect(Circle a, Circle b) {
		// ref
		// http://gamedev.stackexchange.com/questions/20516/ball-collisions-sticking-together

		// a.setPosX(50);
		// a.setPosY(50);
		// a.setRadius(50);
		// a.setSpeedX(0);
		// a.setSpeedY(0);
		//
		// b.setPosX(90);
		// b.setPosY(50);
		// b.setRadius(50);
		// b.setSpeedX(-5);
		// b.setSpeedY(0);

		double xDist, yDist;
		xDist = a.getPosX() - b.getPosX();
		yDist = a.getPosY() - b.getPosY();
		double distSquared = xDist * xDist + yDist * yDist;
		// Check the squared distances instead of the the distances, same
		// result, but avoids a square root.
		if (distSquared <= (a.getRadius() + b.getRadius())
				* (a.getRadius() + b.getRadius())) {
			double speedXocity = b.getSpeedX() - a.getSpeedX();
			double speedYocity = b.getSpeedY() - a.getSpeedY();
			double dotProduct = xDist * speedXocity + yDist * speedYocity;
			// Neat vector maths, used for checking if the objects moves towards
			// one another.
			if (dotProduct > 0) {
				double collisionScale = dotProduct / distSquared;
				double xCollision = xDist * collisionScale;
				double yCollision = yDist * collisionScale;
				// The Collision vector is the speed difference projected on the
				// Dist vector,
				// thus it is the component of the speed difference needed for
				// the collision.
				double combinedMass = a.getMass() + b.getMass();
				double collisionWeightA = 2 * b.getMass() / combinedMass;
				double collisionWeightB = 2 * a.getMass() / combinedMass;
				a.setSpeedX((float) (a.getSpeedX() + (collisionWeightA * xCollision)));
				a.setSpeedY((float) (a.getSpeedY() + (collisionWeightA * yCollision)));
				b.setSpeedX((float) (b.getSpeedX() - (collisionWeightB * xCollision)));
				b.setSpeedY((float) (b.getSpeedY() - (collisionWeightB * yCollision)));
				
				a.setRadius((float)(a.getRadius()*0.99));
				b.setRadius((float)(b.getRadius()*0.99));
			}
		}
	}

	// public Circle getC1() {
	// return c1;
	// }
	//
	// public void setC1(Circle c1) {
	// this.c1 = c1;
	// }
	//
	// public Circle getC2() {
	// return c2;
	// }
	//
	// public void setC2(Circle c2) {
	// this.c2 = c2;
	// }

	public float getTouchX() {
		return touchX;
	}

	public void setTouchX(float touchX) {
		this.touchX = touchX;
	}

	public float getTouchY() {
		return touchY;
	}

	public void setTouchY(float touchY) {
		this.touchY = touchY;
	}

	public float getTouchXPre() {
		return touchXPre;
	}

	public void setTouchXPre(float touchXPre) {
		this.touchXPre = touchXPre;
	}

	public float getTouchYPre() {
		return touchYPre;
	}

	public void setTouchYPre(float touchYPre) {
		this.touchYPre = touchYPre;
	}

	public int getMoveSpeed() {
		return moveSpeed;
	}

	public void setMoveSpeed(int moveSpeed) {
		this.moveSpeed = moveSpeed;
	}

	public float getSpeedX() {
		return speedX;
	}

	public void setSpeedX(float speedX) {
		this.speedX = speedX;
	}

	public float getSpeedY() {
		return speedY;
	}

	public void setSpeedY(float speedY) {
		this.speedY = speedY;
	}

	public boolean isTouchReleased() {
		return isTouchReleased;
	}

	public void setTouchReleased(boolean isTouchReleased) {
		this.isTouchReleased = isTouchReleased;
	}

	public int getCanvasWidth() {
		return canvasWidth;
	}

	public void setCanvasWidth(int canvasWidth) {
		this.canvasWidth = canvasWidth;
	}

	public int getCanvasHeight() {
		return canvasHeight;
	}

	public void setCanvasHeight(int canvasHeight) {
		this.canvasHeight = canvasHeight;
	}

}
